#ifndef __REDUCTION__
#define __REDUCTION__

#include <optional>
#include <iostream>
#include <stdexcept>

namespace DimN
{

	class _Reduction
	{
	public:
		_Reduction() {}

        static int get_enum(const std::string& reduction) {
            if (reduction == "none") {
                return 0;
            }
            else if (reduction == "mean" || reduction == "elementwise_mean") {
                if (reduction == "elementwise_mean") {
                    std::cerr << "Warning: 'elementwise_mean' is deprecated, please use 'mean' instead." << std::endl;
                }
                return 1;
            }
            else if (reduction == "sum") {
                return 2;
            }
            else {
                throw std::invalid_argument(reduction + " is not a valid value for reduction");
            }
        }


        static std::string legacy_get_string(const std::optional<bool>& size_average, const std::optional<bool>& reduce, bool emit_warning = true) {
            std::string warning = "size_average and reduce args will be deprecated, please use reduction='{}' instead.";

            bool effective_size_average = size_average.value_or(true);
            bool effective_reduce = reduce.value_or(true);

            std::string ret;
            if (effective_size_average && effective_reduce) {
                ret = "mean";
            }
            else if (effective_reduce) {
                ret = "sum";
            }
            else {
                ret = "none";
            }

            if (emit_warning) {
                std::cerr << "Warning: " << warning.replace(warning.find("{}"), 2, ret) << std::endl;
            }

            return ret;
        }

        static int legacy_get_enum(const std::optional<bool>& size_average, const std::optional<bool>& reduce, bool emit_warning = true) {
            std::string reduction = legacy_get_string(size_average, reduce, emit_warning);
            return get_enum(reduction);
        }





	};



};


#endif